/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package javaapplication1;

/**
 *
 * @author apple
 */
public class Roads {
    /*
     * used -1 becuase no way of checking if a variable has been initialezed
     * also because user input menu 3 and 4 can contain 0 value;
     * http://stackoverflow.com/questions/2623125/how-do-i-check-if-a-variable-has-been-initialized
     *
     */
    private static int h_lane = -1;//number of h lanes
    private static int v_lane = -1;//number of v lanes
    private static int h_car = -1;//number of h cars
    private static int v_car = -1;//number of v cars
    private static int cycles = -1;// number of cycles
    private static final int h_grid = 21;//h road size - unchanged hence finial
    private static final int v_grid = 21;//h road size - unchanged hence finial
    private static char[][] grid_array;//2d array
    private static int h_middle = h_grid / 2;
    private static int v_middle = v_grid / 2;

    /**
     * assign constant value for green light
     * Green 13 to 22
     */
    public static final int LGITH_GREEN = 22;
    /**
     * assign constant value for yellow light
     * Yellow 10 - 12
     */
    public static final int LGITH_YELLOW = 12;
    /**
     * assign constant value for red light
     * Red 1 - 9
     */
    public static final int LGITH_RED = 9;

    /**
     * assign constant value for grass, for use in array_grid
     *
     */
    public static final char ROAD_GRASS = 'G';
    /**
     * assign constant value for intersection, for use in array_grid
     */
    public static final char ROAD_SECTION = 'I';
    /**
     * assign constant value for V Lane, for use in array_grid
     */
    public static final char ROAD_V_LANE = '-';
    /**
     * assign constant value for H Lane, for use in array_grid
     */
    public static final char ROAD_H_LANE = '|';
    /**
     * assign constant value for car, for use in array_grid
     */
    public static final char ROAD_CAR = 'C';
    /**
     * assign constant value for space, for use in array_grid
     */
    public static final char ROAD_SPACE = ' ';


    private static int h_Lights = LGITH_GREEN;
    private static int v_Lights = LGITH_RED;

    /**
     * getter for H light
     *
     * @return current H light
     */
    public static int getH_Lights() {
        return h_Lights;
    }

    /**
     * getter for V light
     *
     * @return current v light
     */
    public static int getV_Lights() {
        return v_Lights;
    }
    /**
     * switch lights function
     *
     * each call will increase both h and v lights value
     * light will change once each reach curtains value
     * @see LGITH_GREEN LIGHT_YELLOW and LIGHT_RED
     */
    public static void switchLights() {
        if (h_Lights == LGITH_GREEN) {
            h_Lights = 1;
        } else {
            h_Lights++;
        }
        if (v_Lights == LGITH_GREEN) {
            v_Lights = 1;
        } else {
            v_Lights++;
        }
    }

    /**
     * display light to see
     *
     * display only 1 light to console depending on param
     * @see display_lights for displaying both lights
     *
     * @param vorh must be h or v, h = horizontal | v = vertical
     */
    public static void display_light(char vorh) {
        String output = "";
        if (vorh == 'v') {
            output += "+-v-+";
            output += "\n";
            output += (getV_Lights() > LGITH_YELLOW) ? "+-G-+" : "+-*-+";
            output += "\n";
            output += (getV_Lights() > LGITH_RED && getV_Lights() <= LGITH_YELLOW) ? "+-Y-+": "+-*-+";
            output += "\n";
            output += (getV_Lights() <= LGITH_RED) ? "+-R-+" : "+-*-+";
            output += "\n";
            output += "+---+";
            System.out.println(output);
        } else if (vorh == 'h') {
            output += "+-H-+";
            output += "\n";
            output += (getH_Lights() > LGITH_YELLOW) ? "+-G-+" : "+-*-+";
            output += "\n";
            output += (getH_Lights() > LGITH_RED && getH_Lights() <= LGITH_YELLOW) ? "+-Y-+": "+-*-+";
            output += "\n";
            output += (getH_Lights() <= LGITH_RED) ? "+-R-+" : "+-*-+";
            output += "\n";
            output += "+---+";
            System.out.println(output);
        }
    }
    /**
     * display both h and v lights
     *
     * display both horizontal and vertical traffic light to console
     * unlike display_light(char) only display 1 light, this function display both light
     *
     */
    public static void display_lights() {
        String output = "";
        output += "      Lights ";
        output += "\n";
        output += "    H        V ";
        output += "\n";
        output += "  +---+    +---+  ";
        output += "\n";
        output += (getH_Lights() > LGITH_YELLOW) ? "  +-G-+  " : "  +-*-+  ";
        output += (getV_Lights() > LGITH_YELLOW) ? "  +-G-+  " : "  +-*-+  ";
        output += "\n";
        output += (getH_Lights() > LGITH_RED && getH_Lights() <= LGITH_YELLOW) ? "  +-Y-+  ": "  +-*-+  ";
        output += (getV_Lights() > LGITH_RED && getV_Lights() <= LGITH_YELLOW) ? "  +-Y-+  ": "  +-*-+  ";
        output += "\n";
        output += (getH_Lights() <= LGITH_RED) ? "  +-R-+  " : "  +-*-+  ";
        output += (getV_Lights() <= LGITH_RED) ? "  +-R-+  " : "  +-*-+  ";
        output += "\n";
        output += "  +---+    +---+  ";
        System.out.println(output);
    }
    /**
     * getter for Grid_array
     *
     * this 2d array contains our road structural
     * @return grid_array
     */
    public static char[][] getGrid_array() {
        return grid_array;
    }

    /**
     * setting for grid_array
     *
     * @param array
     */
    public static void setGrid_array(char[][] array) {
        grid_array = array;
    }

    /**
     * getter for cycles simulation
     *
     * @return cycles
     */
    public static int getCycles() {
        return cycles;
    }

    /**
     * setter for cycles simulation
     *
     * @param cycles
     */
    public static void setCycles(int cycles) {
        Roads.cycles = cycles;
    }

    /**
     * getter for h car
     *
     * @return number of h car
     */
    public static int getH_car() {
        return h_car;
    }

    /**
     * setter for h car
     * 
     * @param h_car
     */
    public static void setH_car(int h_car) {
        Roads.h_car = h_car;
    }

    /**
     * getter for h_grid
     * @return a number of h grid
     */
    public static int getH_grid() {
        return h_grid;
    }

    /**
     * getter for h_lane
     *
     * @return number of h lane
     */
    public static int getH_lane() {
        return h_lane;
    }

    /**
     * setter for h_lane
     *
     * @param h_lane number of h lane in int
     */
    public static void setH_lane(int h_lane) {
        Roads.h_lane = h_lane;
    }

    /**
     * getter for v car
     * @return number of cars terveling vertically
     */
    public static int getV_car() {
        return v_car;
    }

    /**
     * setter for v car
     * @param v_car number of cars going vertically
     */
    public static void setV_car(int v_car) {
        Roads.v_car = v_car;
    }

    /**
     * getter for v grid
     *
     * @return v grid
     */
    public static int getV_grid() {
        return v_grid;
    }

    /**
     * getting for v lane
     * @return v lane
     */
    public static int getV_lane() {
        return v_lane;
    }

    /**
     * setter for v lane
     * @param v_lane
     */
    public static void setV_lane(int v_lane) {
        Roads.v_lane = v_lane;
    }
    /**
     * create grid array for road
     */
    public static void init() {
        grid_array = new char[h_grid][v_grid];//2d array
    }
    /**
     * main run function for Roads class
     *
     * each call to this function will do the following:
     * 1. loop thru 2d road grid_array(char) array
     * 2. each loop will determine the position of the value
     * 3. if the location is a road we call Cars.move and pass the following
     *    arg 1: x or y, x = horizontal | y = vertical
     *    arg 2: vertical position of the array
     *    arg 3: horizontal position of the array
     *    arg 4: road type - either ON_ROAD or ON_SECTION
     *
     */
    public static void run() {
        for (int h = 0; h < grid_array.length; h++ ) {
            for (int v = 0; v < grid_array[h].length; v++ ) {
                if((v <= h_middle + v_lane) && (v >= h_middle - v_lane) && (h <= h_middle + h_lane) && (h >= h_middle - h_lane)) {//intersection
                    grid_array[h][v] = 'I';
                    Cars.move('h', v, h, Cars.ON_SECTION);
                    Cars.move('v', v, h, Cars.ON_SECTION);
                } else if ((v <= h_middle + v_lane) && (v >= h_middle - v_lane)) {
                    if (checkEven(v)) {
                        grid_array[h][v] = (!checkEven(v_lane)) ? Cars.move('v', v, h, Cars.ON_RAOD) : Roads.ROAD_H_LANE;
                    } else {
                        grid_array[h][v] = (checkEven(v_lane)) ? Cars.move('v', v, h, Cars.ON_RAOD) : Roads.ROAD_H_LANE;
                    }
                } else if ((h <= h_middle + h_lane) && (h >= h_middle - h_lane)) {
                    if (checkEven(h)) {
                        grid_array[h][v] = (!checkEven(h_lane)) ? Cars.move('h', v, h, Cars.ON_RAOD) : Roads.ROAD_V_LANE;
                    } else {
                        grid_array[h][v] = (checkEven(h_lane)) ? Cars.move('h', v, h, Cars.ON_RAOD) : Roads.ROAD_V_LANE;
                    }
                } else {
                    grid_array[h][v] = Roads.ROAD_GRASS;
                }
            }
        }


    }
    /**
     * display output to console
     *
     * display output to console, this function assumes Roads.run has been called
     * no error checking allowed
     */
    public static void display() {
        String output = "";
        //loop grid again to display car opsition
        //must do this in a second loop incase car move to backwards diraction
        for (int h = 0; h < grid_array.length; h++ ) {
            for (int v = 0; v < grid_array[h].length; v++ ) {

                if (grid_array[h][v] == Roads.ROAD_GRASS) {
                    output += ' ';
                } else if(grid_array[h][v] == Roads.ROAD_SECTION) {
                    output += (Cars.moveDisplay(v, h) == true) ? Roads.ROAD_CAR : Roads.ROAD_SPACE;
                } else {
                    output += (Cars.moveDisplay(v, h) == true) ? Roads.ROAD_CAR : grid_array[h][v];
                }
            }
            output += "\n";
        }
        Cars.moveDebug();
        Cars.moveReset();
        System.out.println(output);

        Roads.switchLights();
        Roads.display_lights();
        output = "";
    }
    /**
     * check number if is a even number
     *
     * simply function to check if a number(int) is a even number
     *
     * @param num number to check
     * @return return true if it is even
     */
    public static boolean checkEven(int num) {
        boolean even;
        if (num % 2 == 0) {
            even = true;
        } else {
            even = false;
        }
        return even;
    }

}
